package i3.ui.option;

import java.awt.Component;
import java.awt.Dimension;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.DefaultListModel;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 *
 * @author  i30817
 */
public final class BooleanOptions extends javax.swing.JPanel implements Iterable<Entry<String, Boolean>> {

    /** Creates new form BooleanOptions */
    public BooleanOptions() {
        super();
        initComponents();
        booleanList.addListSelectionListener(
                new ListSelectionListener() {

                    public void valueChanged(ListSelectionEvent e) {
                        if (e.getValueIsAdjusting()) {
                            return;
                        }

                        booleanSelectionChanged(e);
                    }
                });

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jScrollPane1 = new javax.swing.JScrollPane();
        booleanList = new javax.swing.JList<String>(new javax.swing.DefaultListModel<String>());
        showButton = new javax.swing.JToggleButton();
        hideButton = new javax.swing.JToggleButton();
        buttonGroup1.add(showButton);
        buttonGroup1.add(hideButton);
        textPane = new javax.swing.JTextArea();

        jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        booleanList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jScrollPane1.setViewportView(booleanList);

        showButton.setText("Show");
        showButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showButtonPressed(evt);
            }
        });

        hideButton.setText("Hide");
        hideButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                hideButtonPressed(evt);
            }
        });

        textPane.setEditable(false);
        textPane.setColumns(20);
        textPane.setLineWrap(true);
        textPane.setRows(5);
        textPane.setWrapStyleWord(true);
        textPane.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
        textPane.setFocusable(false);
        textPane.setMargin(new java.awt.Insets(3, 3, 3, 3));
        textPane.setMinimumSize(new java.awt.Dimension(0, 0));
        textPane.setOpaque(false);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(showButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(hideButton))
                    .addComponent(textPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 184, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(textPane, javax.swing.GroupLayout.PREFERRED_SIZE, 141, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(hideButton)
                            .addComponent(showButton))))
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    private void hideButtonPressed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hideButtonPressed
        Object key = booleanList.getSelectedValue();
        Boolean oldBoolean = booleanMap.get(key);
        booleanMap.put(key.toString(), Boolean.FALSE);
        firePropertyChange(key.toString(), oldBoolean, Boolean.FALSE);
    }//GEN-LAST:event_hideButtonPressed

    private void showButtonPressed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showButtonPressed
        Object key = booleanList.getSelectedValue();
        Boolean oldBoolean = booleanMap.get(key);
        booleanMap.put(key.toString(), Boolean.TRUE);
        firePropertyChange(key.toString(), oldBoolean, Boolean.TRUE);
    }//GEN-LAST:event_showButtonPressed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JList<String> booleanList;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JToggleButton hideButton;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JToggleButton showButton;
    private javax.swing.JTextArea textPane;
    // End of variables declaration//GEN-END:variables
    private final Map<String, Boolean> booleanMap = new HashMap<>();
    private final Map<String, String> descriptionMap = new HashMap<>();

    private void booleanSelectionChanged(ListSelectionEvent e) {
        String key = booleanList.getSelectedValue();
        String desc = descriptionMap.get(key);
        textPane.setText(desc);
        boolean active = booleanMap.get(key);
        if (active) {
            buttonGroup1.setSelected(showButton.getModel(), true);
        } else {
            buttonGroup1.setSelected(hideButton.getModel(), true);
        }
    }

    public void updateSize() {
        int width = 1;
        ListModel<String> m = booleanList.getModel();
        ListCellRenderer<? super String> lcr = booleanList.getCellRenderer();
        for (int i = 0; i < m.getSize(); i++) {
            String o = m.getElementAt(i);
            Component c = lcr.getListCellRendererComponent(booleanList, o, 0, false, false);
            Dimension dim = c.getPreferredSize();
            width = Math.max(dim.width, width);
        }
        width = (int) (width + jScrollPane1.getVerticalScrollBar().getPreferredSize().getWidth());
        jScrollPane1.setPreferredSize(new Dimension(width, -1));
    }

    /**
     * Adds a boolean option. Always sends the current value and a old value of !current
     * to registered listeners (it is supposted to be current, so it won't change if it really is,
     * and saves some code if it isn't).
     * @param name not null
     * @param current not null
     */
    public void addBooleanOption(String name, Boolean current, String booleanValueDescription) {
        if (name == null || current == null) {
            throw new IllegalArgumentException("Name or current boolean is null");
        }

        if (!booleanMap.containsKey(name)) {
            DefaultListModel<String> mod = (DefaultListModel<String>) booleanList.getModel();
            mod.addElement(name);
        }
        booleanMap.put(name, current);
        descriptionMap.put(name, booleanValueDescription);
        //Always set the current value...
        firePropertyChange(name, Boolean.valueOf(!current), current);
        if (booleanList.getSelectedIndex() == -1) {
            booleanList.setSelectedIndex(0);
        }
    }

    public Boolean get(String name) {
        return booleanMap.get(name);
    }

    public void put(String name, Boolean v) {
        booleanMap.put(name, v);
    }

    @Override
    public Iterator<Entry<String, Boolean>> iterator() {
        return booleanMap.entrySet().iterator();
    }
}
